package control.character;

import com.jme3.bounding.BoundingVolume;
import com.jme3.collision.CollisionResult;
import com.jme3.collision.CollisionResults;
import com.jme3.math.Ray;
import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;
import com.jme3.renderer.Camera.FrustumIntersect;
import com.jme3.scene.Spatial;
import com.jme3.scene.control.CameraControl;
import com.jme3.scene.control.Control;
import game.DataStore;
import game.constant.Constants;

public class SimpleAIControl extends AbstractAIControl {

    public SimpleAIControl() {}

    @Override
    protected void controlUpdate(float tpf) {
	super.controlUpdate(tpf);
	checkForPlayerSight();
    }

    @Override
    public void collideWith(Spatial collidingSpatial) {
	if(!collidingSpatial.getName().equals("floor")) {
	    if(DataStore.physicsHubNode.hasChild(collidingSpatial)) {
		characterControl.setHeldObject(collidingSpatial);
	    } else {
		setRandomWalkDirection();
	    }
	}
    }

    protected void checkForPlayerSight() {
	//TODO try adding a light level check (yeah, right)
	//idea: raycast on rootnode from each light source to the point (first check to see if the point is within
	//the radius of the light; if not, ignore that light) if the ray returns no collisions,
	//scale the light relative to its radius and distance to the point and add it to a running sum.
	//total sum == relative light level at point. genius!
	
        //frustum checking. NOTE: this only determines if the player is in the cam's frustum, regardless of z-index!
	Camera cam = spatial.getControl(CameraControl.class).getCamera();
	BoundingVolume bv = DataStore.player.getWorldBound();
	//save plane state values
	int bvPS = bv.getCheckPlane();
	int camPS = cam.getPlaneState();
	//temporarily set plane states to 0 before doing a manual contains check
	bv.setCheckPlane(0);
	cam.setPlaneState(0);
	//get results of contains
	FrustumIntersect fi = cam.contains(bv);
	//restore plane states
	cam.setPlaneState(camPS);
	bv.setCheckPlane(bvPS);
	if (fi == FrustumIntersect.Inside || fi == FrustumIntersect.Intersects) {
            //player is inside the frustum, now check z-index
            CollisionResults results = new CollisionResults();
            Ray ray = new Ray(cam.getLocation(), DataStore.player.getWorldTranslation().subtract(cam.getLocation()));
            DataStore.rootNode.collideWith(ray, results);
            if (results.size() > 0) {
                CollisionResult closestResult = results.getCollision(0);
                if (closestResult.getGeometry().equals(DataStore.player)) {
                    Vector3f newDir = DataStore.player.getWorldTranslation().subtract(characterControl.getPhysicsLocation());
                    newDir.setY(0f);
                    newDir.normalizeLocal().multLocal((Float)spatial.getUserData(Constants.CHARACTER_CURRENT_SPEED)/100f);
                    spatial.setUserData(Constants.AI_CURRENT_WALK_DIR, newDir);
                }
            }
	}
    }

    @Override
    public Control cloneForSpatial(Spatial spatial) {
	SimpleAIControl control = new SimpleAIControl();
        // copy custom properties here?
        spatial.addControl(control);
        return control;
    }
}
